/**
 * 
 */
package org.timemanager.view;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

/**
 * data backup for sqlite database
 * @author Dereky
 *
 */
public class BackupDialog extends Dialog {

	private ListView list;
	private SimpleAdapter dataAdapter;
	private List<Map<String, Object>> dataList = new ArrayList<Map<String,Object>>();

	private Context context;
	
	/**
	 * record current path
	 */
	private String path;
	private String defaultText;

	private View panel;
	private Button home;
	private Button back;
	private Button ok;
	private EditText filename;

	/**
	 * 1 means import backup file<br/>
	 * 2 means export sqlite database
	 */
	private int type = 1;
	
	private DataExchange dataExchange;
	
	public static final int OPEN = 1;
	public static final int SAVE = 2;

	/**
	 * 
	 * @param context
	 * @param type 1 means import; 2 means export
	 * @param defaultText filename editor's default text
	 */
	public BackupDialog(Context context, int type, 
			DataExchange dataExchange,String defaultText) {
		super(context);
		this.context = context;
		this.type = type;
		this.dataExchange = dataExchange;
		this.defaultText = defaultText;
	}

	@Override
	public void show() {
		if(getSDPath() == null){
			Toast.makeText(context, context.getText(R.string.no_sdcard), Toast.LENGTH_LONG).show();
			return;
		}
		super.show();
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		if(getSDPath() == null){
			return;
		}
		super.onCreate(savedInstanceState);
		setContentView(R.layout.backup_dlg);

		list = (ListView) findViewById(R.id.backup_list);
		dataAdapter = new SimpleAdapter(context, dataList, R.layout.backup_list_item, 
				new String[]{"icon","filename"}, new int[]{R.id.backup_icon_item,R.id.backup_filename_item});
		list.setAdapter(dataAdapter);
		list.setOnItemClickListener(new OnItemClickListener() {
			
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				
				String temp = (String) dataList.get(position).get("filename");
				if ("..".equals(temp)){
					path = getSubDir(path);
					updateList();
				}else if (".".equals(temp)){
					return;
				}else {
					String newPath = path + "/" + temp;
					if(type == OPEN){
						if(isFile(newPath)){
							String targetFile = newPath;
							hide();
							if(dataExchange.restore(targetFile)){
								alertMsg(R.string.import_success);
								dismiss();
								((TimeManagerActivity)context).resetViews();
							}
							else{
								alertMsg(R.string.import_fail);
								show();
							}
						}else{
							path = newPath;
							updateList();
						}
					}else{
						if(!isFile(newPath)){
							path = newPath;
							updateList();
						}
					}
				}
			}
		});

		home = (Button) findViewById(R.id.backup_home);
		home.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				init();
			}
		});

		back = (Button) findViewById(R.id.backup_back);
		back.setOnClickListener(new View.OnClickListener() {
		
			public void onClick(View v) {
				path = getSubDir(path);
				updateList();
			}
		});

		filename = (EditText)findViewById(R.id.backup_filename);
		filename.setText(defaultText);
		filename.addTextChangedListener(new TextWatcher() {
		
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				// TODO Auto-generated method stub
				
			}
		
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// TODO Auto-generated method stub
				
			}
		
			public void afterTextChanged(Editable s) {
				if("".equals(s.toString())){
					ok.setEnabled(false);
				}else{
					ok.setEnabled(true);
				}
			}
		});
		
		ok = (Button) findViewById(R.id.backup_ok);
		ok.setOnClickListener(new View.OnClickListener() {
		
			public void onClick(View v) {
				String targetFile = path + "/" + filename.getText();
				hide();
				if(dataExchange.save(targetFile)){
					alertMsg(R.string.export_success);
					dismiss();
				}else{
					alertMsg(R.string.export_fail);
					show();
				}
			}
		});
		if(defaultText == null || "".equals(defaultText)){
			ok.setEnabled(false);
		}
		
		panel = findViewById(R.id.backup_panel);
		if (type == OPEN) {
			setTitle(R.string.import_backup_title);
			panel.setVisibility(View.GONE);
		} else if (type == SAVE) {
			setTitle(R.string.export_backup_title);
			panel.setVisibility(View.VISIBLE);
		}
		
		init();
	}
	
	public void alertMsg(int msgResId){
		new AlertDialog.Builder(context).
				setTitle(type == OPEN? R.string.import_backup_title: R.string.export_backup_title).
				setMessage(msgResId).
				setPositiveButton(android.R.string.ok, null).
				show();
	}
	
	public void init(){
		path = getSDPath();
		if(path == null){
			Toast.makeText(context, context.getText(R.string.no_sdcard), Toast.LENGTH_LONG).show();
			dismiss();
			return;
		}
		updateList();
	}
	
	public void updateList(){
		Handler handler = new Handler();
		handler.post(listUpdater);
	}
	
	Runnable listUpdater = new Runnable() {

		public void run() {
			if(getSDPath().equals(path)){
				back.setEnabled(false);
			}else{
				back.setEnabled(true);
			}
			
			//it must be written like this, then it works
			dataList.clear();
			List<Map<String, Object>> tmp = getDirs(path);
			
			Collections.sort(tmp, new Comparator<Map<String, Object>>() {

				public int compare(Map<String, Object> lhs, Map<String, Object> rhs) {
					return ((String)lhs.get("filename")).compareTo((String)rhs.get("filename"));
				}
			});
			
			for(Map<String, Object> item : tmp){
				dataList.add(item);
			}
			
			dataAdapter.notifyDataSetChanged();
		}
	};

	public boolean isFile(String file){
		return !(new File(file).isDirectory());
	}
	
	public List<Map<String, Object>> getDirs(String ipath) {
		List<Map<String, Object>> fileList = new ArrayList<Map<String, Object>>();
		File[] myFile = new File(ipath).listFiles();
		if (myFile != null) {
			for (File f : myFile) {
				if (f.isDirectory()) {
					String tempf = f.toString();
					int pos = tempf.lastIndexOf("/");
					String subTemp = tempf.substring(pos + 1, tempf.length());
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("icon", R.drawable.folder);
					map.put("filename", subTemp);
					fileList.add(map);
				}
				else if (f.isFile()) {
					String subTemp = f.toString().substring(path.length() + 1,
							f.toString().length());
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("icon", R.drawable.plain_file);
					map.put("filename", subTemp);
					fileList.add(map);
				}
			}
		}
		
		Collections.sort(fileList, new Comparator<Map<String, Object>>() {

			public int compare(Map<String, Object> lhs, Map<String, Object> rhs) {
				return ((String)lhs.get("filename")).compareTo((String)rhs.get("filename"));
			}
		});
		
		return fileList;
	}

	private static String getSDPath() {
		File sdDir = null;
		boolean sdCardExist = Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED);
		if (sdCardExist) {
			sdDir = Environment.getExternalStorageDirectory();
		}
		if (sdDir == null) {
			return null;
		}
		return sdDir.toString();
	}

	/**
	 * get parent directory
	 */
	private String getSubDir(String path) {
		String sdcard = getSDPath();
		if(sdcard == null){
			Toast.makeText(context, context.getText(R.string.no_sdcard), Toast.LENGTH_LONG).show();
			dismiss();
			return "";
		}
		if(sdcard.equals(path)){
			return sdcard;
		}
		
		String subpath = null;
		int pos = path.lastIndexOf("/");

		if (pos == path.length()) {
			path = path.substring(0, path.length() - 1);
			pos = path.lastIndexOf("/");
		}

		subpath = path.substring(0, pos);
		return subpath;
	}
}
